/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 *
 */

import { ClassTypeConst } from '../../../common/options/class-type-const.js';
import { HvigorCoreNode } from '../../../external/core/hvigor-core-node.js';
import { HvigorTaskGroupType } from '../../../external/task/core-task.js';
import { IncrementalTask } from '../../../external/task/incremental-task.js';
import { FileSet } from '../../../internal/snapshot/util/file-set.js';
import { TaskInputValue } from '../../../internal/snapshot/util/task-input-value-entry.js';
import { HvigorLogger } from '../../../log/hvigor-log.js';
import { HvigorTask, HvigorTaskContext } from '../interface/hvigor-task.js';
import { TaskInput, TaskOutput } from '../interface/input-output.js';

/**
 * hvigorTask转换为CoreTask
 *
 * @since 2023/12/20
 */
export class TransformHvigorTask extends IncrementalTask {
  private logger: HvigorLogger = HvigorLogger.getLogger(TransformHvigorTask.name);
  private _inputs: Map<string, TaskInputValue>;
  private _inputFiles: FileSet;
  private _outputFiles: FileSet;
  protected task: HvigorTask;
  protected taskContext: any;
  protected taskRunContext: HvigorTaskContext;

  constructor(node: HvigorCoreNode, task: HvigorTask) {
    super(node, { name: task.name, group: HvigorTaskGroupType.CUSTOMIZE_TASK_GROUP });
    this.task = task;

    this._inputs = super.declareInputs();
    this._inputFiles = super.declareInputFiles();
    this._outputFiles = super.declareOutputFiles();
    this.taskRunContext = this.getTaskParam();
  }

  initTaskContext(): void {
    this.taskContext = {
      ...this.task,
      context: this.task.context?.apply(),
    };

    this.task.input?.apply(this.taskContext, [new TaskInput(this._inputs, this._inputFiles)]);
    this.task.output?.apply(this.taskContext, [new TaskOutput(this._outputFiles)]);
  }

  initDependency() {
    const taskName = `${this.taskRunContext.moduleName}:${this.task.name}`;
    if (this.task.dependencies && Array.isArray(this.task.dependencies)) {
      for (const dependency of this.task.dependencies) {
        this.logger.debug(`hvigorfile, registering dependency, taskName=${taskName}, dependency=${dependency}`);
        this.dependsOn(dependency);
      }
    }

    if (this.task.postDependencies && Array.isArray(this.task.postDependencies)) {
      for (const postDependency of this.task.postDependencies) {
        this.logger.debug(`hvigorfile, registering postDependency, taskName=${taskName},
         postDependency=${postDependency}`);

        this.initPostDependencyTask(postDependency, taskName);
      }
    }
  }

  // 通过设置postDependency，将自定义任务挂上任务执行流程
  initPostDependencyTask(postDependency: string, taskName: string){
    // lazy task挂载方式，尝试获取task的creationAction对象来操作
    const postTaskCA = this.node.getTaskCAByName(postDependency);
    if (postTaskCA) {
      // 存在postTaskCA，则走懒加载的逻辑加入任务
      this.logger.debug('hvigorfile, registering postDependency through lazy task creationAction');
      this.node.getName() === ClassTypeConst.HVIGOR_PROJECT ? postTaskCA.dependsDefinedByUser.push(`:${this.task.name}`) : postTaskCA.dependsDefinedByUser.push(`${this.node.getName()}:${this.task.name}`);
    } else {
      // 如果获取不到，则尝试当做普通任务处理，走原本的代码逻辑
      const postTask = this.node.getTaskByName(postDependency);
      if (!postTask){
        this.logger.warn(`${taskName}, postDependency ${postDependency} not found.`);
        return;
      }
      postTask.dependsOn(this.task.name, this.node);
    }
  }

  initTaskRun(): void {
    if (this.task.beforeRun && typeof this.task.beforeRun === 'function') {
      super.beforeRun(async () => {
        const hookEvent = this.durationEvent?.createSubEvent('"beforeRun" hook function', '').start();
        await (this.task.beforeRun! as Function).apply(this.taskContext, [this.taskRunContext]);
        hookEvent?.stop().setLog();
      });
    }

    if (this.task.afterRun && typeof this.task.afterRun === 'function') {
      super.afterRun(async () => {
        const hookEvent = this.durationEvent?.createSubEvent('"afterRun" hook function', '').start();
        await (this.task.afterRun! as Function).apply(this.taskContext, [this.taskRunContext]);
        hookEvent?.stop().setLog();
      });
    }
  }

  getAction(): Function {
    return this.doTaskAction;
  }

  async doTaskAction() {
    if (this.task.run && typeof this.task.run === 'function') {
      await (this.task.run! as Function).apply(this.taskContext, [this.taskRunContext]);
    }
  }

  getTaskParam(): HvigorTaskContext {
    return {
      moduleName: this.node.getName(),
      modulePath: this.node.getNodeDir(),
    };
  }

  declareInputs(): Map<string, TaskInputValue> {
    return this._inputs;
  }

  declareInputFiles(): FileSet {
    return this._inputFiles;
  }

  declareOutputFiles(): FileSet {
    return this._outputFiles;
  }
}
